require "Common/define"
require "Logic/Config"
require "Common/functions"

---@class RuneManager
RuneManager = RuneManager or {}
local this = RuneManager
local heroRuneMap = {}  --英雄穿身上的符文
local stuffRuneList = {}    --空闲的符文(当前未被穿戴)
local specialRuneIndex = 6  --天穹符文index

function RuneManager.init()
    this.runeCfg = dataTable.getDataTable("t_rune")
    this.runeStrengthCfg = dataTable.getDataTable("t_runestrengthen")
    this.runeSuit = dataTable.getDataTable("t_runesuit")
end

function RuneManager.SaveHeroRuneData(data)
    for k,v in pairs(data) do
        if not heroRuneMap[v.partnerId] then
            heroRuneMap[tostring(v.partnerId)] = {}
        end
        for m,n in pairs(v.items) do
            local runeInfo = this.FormationRuneInfo(n, v.partnerId)
            local index = runeInfo.index
            if not heroRuneMap[tostring(v.partnerId)][index] then
                heroRuneMap[tostring(v.partnerId)][index] = {}
            end
            heroRuneMap[tostring(v.partnerId)][index] = runeInfo
        end
    end
end

function RuneManager.ExchageHeroRuneData(hero1,index1,hero2,index2)
    local runeInfo = nil
    local otherRuneInfo = nil
    runeInfo = this.GetHeroRuneSrvInfo(hero1, index1)
    otherRuneInfo = this.GetHeroRuneSrvInfo(hero2, index2)
    otherRuneInfo.partnerId = tostring(hero1)
    otherRuneInfo.index = index1
    local dic = {}
    if runeInfo then
        runeInfo.partnerId = tostring(hero2)
        runeInfo.index = index2
        dic.runeAId = runeInfo.itemModelId
    end
    dic.partnerAId = tostring(hero1)
    dic.partnerBId = tostring(hero2)
    dic.runeBId = otherRuneInfo.itemModelId
    TAManager.TrackByDictionary("RuneExchange",dic)
    this.SetHeroRuneSrvInfo(hero1, index1, otherRuneInfo)
    this.SetHeroRuneSrvInfo(hero2, index2, runeInfo)
end

function RuneManager.AddStuffRune(data)
    table.insert(stuffRuneList, data)
end

function RuneManager.UpDataStuffRuneData(itemId, num)
    for k,v in pairs(stuffRuneList) do
        if tostring(v.itemId) == itemId then
            v.num = tonumber(num)
        end
    end
    FireEvent(Config.EventType.FreshHeroRune)
end

function RuneManager.DeleteStuffRuneData(itemId)
    for k,v in pairs(stuffRuneList) do
        if v.itemId == tostring(itemId) then
            table.remove(stuffRuneList,k)
        end
    end
    FireEvent(Config.EventType.FreshHeroRune)
end

function RuneManager.ResHeroRuneData(msg)
    if heroRuneMap[msg.partnerId] then
        local js = decodeJsonStrToTabel(data.parameters)
        if js then
            local index = js.RUNE_INDEX
            if heroRuneMap[msg.partnerId][index] then
                heroRuneMap[msg.partnerId][index].partnerId = nil
                heroRuneMap[msg.partnerId][index] = msg.item
            end
        end

    end
end

function RuneManager.GetRunePower(id, Lv)
    local cfg = this.GetRuneCfgInfo(id,Lv)
    return cfg.f_Power or 0
end

--某个英雄身上的符文
function RuneManager.GetHeroRuneSrvInfo(heroId, index)
    if heroId and heroRuneMap[tostring(heroId)] then
        if index then
            return heroRuneMap[tostring(heroId)][index]
        else
            return  heroRuneMap[tostring(heroId)]
        end
    end
end

function RuneManager.SetHeroRuneSrvInfo(heroId, index, runeInfo)
    if not heroRuneMap[tostring(heroId)] then
        heroRuneMap[tostring(heroId)] = {}
    end
    if not heroRuneMap[tostring(heroId)][index] then
        heroRuneMap[tostring(heroId)][index] = {}
    end
    heroRuneMap[tostring(heroId)][index] = runeInfo
end

function RuneManager.GetHeroStuffRuneIndexList(heroId)
    local indexList = {0,1,2,3,4,5,6}
    local heroRuneData = this.GetHeroRuneSrvInfo(heroId)
    if not heroRuneData then return indexList end
    for i = 0,6 do
        if heroRuneData[i] then
            table.removeByValue(indexList, i)
        end
    end
    return indexList
end

--脱下英雄身上所有符文
function RuneManager.TaskOffHeroRune(heroId)
    if heroRuneMap[heroId] then
        heroRuneMap[heroId] = nil
    end
end

function RuneManager.GetStuffRuneList()
    return stuffRuneList
end

function RuneManager.GetHaveCommonStuffRune()
    for k,v in pairs(stuffRuneList) do
        if v.commonType == 1 then
            return true
        end
    end
    return false
end

function RuneManager.GetCommonStuffRuneList()
    local list = {}
    for k,v in pairs(stuffRuneList) do
        if v.commonType == 1 then
            table.insert(list,v)
        end
    end
    table.sort(list, function(a,b)
        if a.power ~= b.power then
            return a.power > b.power
        else
            return a.itemModelId < b.itemModelId
        end
    end)
    return list
end

function RuneManager.GetSpecialStuffRuneList()
    local list = {}
    for k,v in pairs(stuffRuneList) do
        if v.commonType == 2 then
            table.insert(list,v)
        end
    end
    table.sort(list, function(a,b)
        if a.power ~= b.power then
            return a.power > b.power
        else
            return a.itemModelId < b.itemModelId
        end
    end)
    return list
end

function RuneManager.GetHaveSpecialStuffRune()
    for k,v in pairs(stuffRuneList) do
        if v.commonType == 2 then
            return true
        end
    end
    return false
end

function RuneManager.GetRuneCfgInfo(runeId, level)
    if not runeId then return end
    if level then
        for k,v in pairs(this.runeStrengthCfg) do
            if v.f_RuneId == runeId and v.f_Strengthen_lv == level then
                return v
            end
        end
        return nil
    else
        return this.runeCfg[tostring(runeId)]
    end
end

--获取升到下一等级需要消耗的经验
function RuneManager.GetRuneLevelUpCost(runeId, level)
    local nextLevelData = this.GetRuneCfgInfo(runeId, level)
    if nextLevelData then
        return nextLevelData.f_CostExp
    end
    return 0
end

--获取某一等级符文分解出来的经验
function RuneManager.GetRuneBaseExp(runeId, level)
    local nextLevelData = this.GetRuneCfgInfo(runeId, level)
    if nextLevelData then
        return nextLevelData.f_BaseExp
    end
    return 0
end

--获取可镶嵌的英雄身上的符文
function RuneManager.GetCanChangeRuneList(heroId, index)
    --获取所有英雄身上的符文
    local allHeroRuneData = this.GetAllHeroRuneList()
    local resList = {}
    --local heroRuneData = this.GetHeroRuneSrvInfo(heroId)
    --if not heroRuneData then--or logicMgr.DivineInspirationManager.GetTableEleCount(heroRuneData) == 0 then
    --    return allHeroRuneData
    --end
    --if heroRuneData then
    --    for k,v in pairs(allHeroRuneData) do
    --        if not (v.partnerId == heroId) then
    --            local canInsert = true
    --            for m,n in pairs(heroRuneData) do
    --                if (v.type == n.type and v.smallType == n.smallType) and v.commonType == n.commonType then
    --                    if n.index ~= index then
    --                        canInsert = false
    --                        break
    --                    end
    --                end
    --            end
    --            if canInsert then
    --                table.insert(resList, v)
    --            end
    --        end
    --    end
    --end
    for k,v in pairs(allHeroRuneData) do
        if not (v.partnerId == heroId) then
            if index == specialRuneIndex then
                if v.commonType == 2 then
                    table.insert(resList, v)
                end
            else
                if v.commonType == 1 then
                    table.insert(resList, v)
                end
            end
        end
    end
    table.sort(resList, function(a,b)
        if a.quality ~= b.quality then
            return a.quality > b.quality
        elseif a.power ~= b.power then
            return a.power > b.power
        else
            return a.itemModelId < b.itemModelId
        end
    end)
    return resList
end

--获取所有英雄身上的符文
function RuneManager.GetAllHeroRuneList()
    local allHeroRuneList = {}
    for k,v in pairs(heroRuneMap) do
        for m,n in pairs(v) do
            table.insert(allHeroRuneList, n)
        end
    end
    return allHeroRuneList
end

--获取可镶嵌的闲置的符文
function RuneManager.GetCanWearRuneList(heroId, index)
    local resList = {}
    local heroRuneData = this.GetHeroRuneSrvInfo(heroId)
    local stuffList = this.GetStuffRuneList()
    table.sort(stuffList, function(a,b)
        if a.quality ~= b.quality then
            return a.quality > b.quality
        elseif a.power ~= b.power then
            return a.power > b.power
        else
            return a.itemModelId < b.itemModelId
        end
    end)
    if not heroRuneData then --or logicMgr.DivineInspirationManager.GetTableEleCount(heroRuneData) == 0 then
        return stuffList
    end
    --for k,v in pairs(stuffList) do
    --    local canInsert = true
    --    for m,n in pairs(heroRuneData) do
    --        if (v.type == n.type and v.smallType == n.smallType) and v.commonType == n.commonType then
    --            if n.index ~= index then
    --                canInsert = false
    --                break
    --            end
    --        end
    --    end
    --    if canInsert then
    --        table.insert(resList, v)
    --    end
    --end
    for k,v in pairs(stuffList) do
        if index == specialRuneIndex then
            if v.commonType == 2 then
                table.insert(resList, v)
            end
        else
            if v.commonType == 1 then
                table.insert(resList, v)
            end
        end
    end
    return resList
end

function RuneManager.FormationRuneInfo(runeItem, partnerId)
    if runeItem then
        local runeInfo = {}
        runeInfo.partnerId = partnerId and tostring(partnerId) or nil
        local js = decodeJsonStrToTabel(runeItem.parameters)
        if js then
            runeInfo.index          = tonumber(js["RUNE_INDEX"]) or 0
            runeInfo.level          = tonumber(js["RUNE_LEVEL"]) or 0
            runeInfo.exp            = tonumber(js["RUNE_EXP"]) or 0
            runeInfo.lockList       = decodeJsonStrToTabel(js["RUNE_PROPERTY_LOCK"]) or {}
            runeInfo.baptismAttr    = decodeJsonStrToTabel(js["RUNE_REFINE_ATTR"]) or {}
        else
            runeInfo.index = 0
            runeInfo.level = 0
            runeInfo.exp = 0
            runeInfo.lockList = {}
            runeInfo.baptismAttr = {}
        end
        local runeCfg = this.GetRuneCfgInfo(tonumber(runeItem.itemModelId),runeInfo.level)
        if runeCfg then
            local runeOriginCfg = this.GetRuneCfgInfo(tostring(runeItem.itemModelId))
            local itemCfg = dataTable.getDataTableByStringId("t_item",runeCfg.f_RuneId)

            runeInfo.itemId        = tostring(runeItem.itemId)
            runeInfo.itemModelId   = runeCfg.f_RuneId
            runeInfo.num           = tonumber(tostring(runeItem.num)) or 1
            runeInfo.name          = getLanguage(itemCfg.f_ItemName)
            runeInfo.icon          = itemCfg.f_Icon
            runeInfo.quality       = itemCfg.f_Quality
            runeInfo.desc          = getLanguage(itemCfg.f_Desc)
            runeInfo.commonType    = runeOriginCfg.f_RuneType
            runeInfo.type          = runeOriginCfg.f_RuneClass
            runeInfo.smallType     = runeOriginCfg.f_RuneSmall
            runeInfo.power         = runeCfg.f_Power
            runeInfo.itemType      = itemCfg.f_BagType
            runeInfo.baseAttr      = runeCfg.f_BaseAttr
            runeInfo.totalAttr     = this.GetRuneTotalAttr(runeInfo)
            return runeInfo
        end
    end
end

function RuneManager.SetHeroRuneItemData(obj,data, partnerId, index)
    local img_Icon = obj:GetChild("icon")
    local txt_Strength = obj:GetChild("strength")
    local type = obj:GetController("suit")
    local ctrlLock = obj:GetController("lock")
    local txtLock = obj:GetChild("text_lock")
    img_Icon.visible = false
    txt_Strength.visible = false
    type.selectedIndex = 0

    local isLock,needQualityName = this.CheckRuneLock(partnerId, index)
    if isLock then
        ctrlLock.selectedIndex = 1
        txtLock.text =  string.format("突破至%s解锁",needQualityName)
    else
        ctrlLock.selectedIndex = 0
    end

    if data ~= nil then
        if data["icon"] ~= nil then
            img_Icon.visible = true
            img_Icon.url = "ui://ItemAtlas/".. data["icon"]
        end
        --if data["quality"] ~= nil then
            --img_Quality.visible = true
            --img_Frame.visible = true
            --img_Frame.url =  EnumConst.AtlasPath.ICONAtlas..Config.IconFrame[tonumber(data["quality"])]
            --img_Quality.url = EnumConst.AtlasPath.ICONAtlas..Config.IconQuality[tonumber(data["quality"])]
        --end
        if data["level"] ~= nil and tonumber(data["level"]) > 0 then
            txt_Strength.visible = true
            txt_Strength.text = "+"..data["level"]
        end
        type.selectedIndex = data["type"]
        --obj_Add.visible = false
    end
end

function RuneManager.CheckRuneLock(partnerId,runeIndex)
    local heroStar = logicMgr.HeroManager.GetHeroStar(partnerId)
    local needStarList = decodeJsonStrToTabel(dataTable.getDataTableByStringId("t_global", 670 ,"f_string_value"))
    if needStarList then
        local needStar = needStarList[runeIndex+1][2] or 0
        if heroStar >= needStar then
            return false
        else
            local needQuality = logicMgr.HeroManager.starToQuality(needStar) or 1
            return true,EnumConst.StarType[needQuality]
        end
    end
end

--设置符文item
function RuneManager.SetRuneItemData(obj,data,noShowHero)
    if obj and data then
        local item = CtrlManager.GetCtrl(PanelNames.Item)
        if item then
            local ctr_debris = obj:GetController("debris")
            local it_debris = obj:GetChild("debris")
            local txt_level = obj:GetChild("refineLevel")
            local ctr_lock = it_debris:GetController("lock")
            ctr_debris.selectedIndex = 1
            it_debris:GetController("owner").selectedIndex = data.partnerId and 1 or 0
            if ctr_lock then
                ctr_lock.selectedIndex = data.lock == 1 and 1 or 0
            end
            item.initData(obj, data, 1, true, nil,  data.partnerId)

            local heroData = logicMgr.HeroManager.getHeroDatabyPartnerId(data.partnerId,true)
            if heroData and (not noShowHero) then
                local url = "ui://ICONAtlas/"..heroData.icon
                it_debris:GetChild("hero"):GetChild("HeadIcon").url = url
            else
                it_debris:GetController("owner").selectedIndex = 0
                it_debris:GetChild("hero"):GetChild("HeadIcon").url = ""
            end
            it_debris:GetChild("Occupation").url = EnumConst.Path_DebrisTypeIcon["type_" .. 1]
            --if data.level > 0 then
            --    txt_level.text = "+"..data.level
            --else
            --    txt_level.text = ""
            --end
        end
    end
end

--天穹技能是否被激活
function RuneManager.CheckSpecialRuneSkillActive(partnerId)
    local specialRuneInfo = this.GetHeroRuneSrvInfo(partnerId, specialRuneIndex)
    if specialRuneInfo then
        local specialRuneSuitCfg = dataTable.getDataTableByStringId("t_runesuit",specialRuneInfo.itemModelId)
        if specialRuneSuitCfg then
            local conditionList = specialRuneSuitCfg.f_Condition or {}
            local needQuality = conditionList[1] or 0
            local needType = conditionList[2] or 0
            local needSmallType = conditionList[3] or 0
            local needCount = conditionList[4] or 1
            local heroRuneData = this.GetHeroRuneSrvInfo(partnerId) or {}
            local haveCount = 0
            local properCount = 0
            local properCommonRuneList = {}
            for k,v in pairs(heroRuneData) do
                if v.type == needType and v.smallType == needSmallType and v.commonType == 1 then
                    table.insert(properCommonRuneList, v)
                    properCount = properCount + 1
                end
                if v.quality >= needQuality and v.type == needType and v.smallType == needSmallType and v.commonType == 1 then
                    haveCount = haveCount + 1
                end
            end
            if properCount >= needCount then
                table.sort(properCommonRuneList, function(a,b)
                    return a.quality > b.quality
                end)
                return true, needCount, properCommonRuneList
            else
                local itemName = this.GetRuneNameByType(1,specialRuneInfo.type,specialRuneInfo.smallType)
                return false, needCount - haveCount, EnumConst.StarType[needQuality],itemName
            end
        end
    else
        return false
    end
end

function RuneManager.GetShowSpecialRune(runeModelId, quality)
    local paraRuneCfg = this.runeCfg[tostring(runeModelId)]
    if paraRuneCfg then
        for k,v in pairs(this.runeCfg) do
            if v.f_Quality == quality and v.f_RuneType == paraRuneCfg.f_RuneType and v.f_RuneClass == paraRuneCfg.f_RuneClass and v.f_RuneSmall == paraRuneCfg.f_RuneSmall then
                return v.f_RuneId
            end
        end
    end
end

function RuneManager.GetNextQualitySpecialRune(runeModelId, quality)
    local paraRuneCfg = this.runeCfg[tostring(runeModelId)]
    local nextQualitySpecialRuneCfg = nil
    if paraRuneCfg then
        for k,v in pairs(this.runeCfg) do
            if v.f_RuneType == paraRuneCfg.f_RuneType and v.f_RuneClass == paraRuneCfg.f_RuneClass and v.f_RuneSmall == paraRuneCfg.f_RuneSmall and  v.f_Quality > quality then
                if nextQualitySpecialRuneCfg then
                    if nextQualitySpecialRuneCfg.f_Quality > v.f_Quality then
                        nextQualitySpecialRuneCfg = v
                    end
                else
                    nextQualitySpecialRuneCfg = v
                end
            end
        end
        return nextQualitySpecialRuneCfg
    end
end

function RuneManager.GetRuneNameByType(commonType, type, smallType)
    local itemModelId
    local itemName = ""
    for k,v in pairs(this.runeCfg) do
        if v.f_RuneType == commonType and v.f_RuneClass == type and v.f_RuneSmall == smallType then
            itemModelId = v.f_RuneId
        end
    end
    if itemModelId then
        local name = dataTable.getDataTableByStringId("t_item", itemModelId, "f_ItemName")
        if name then
            itemName = getLanguage(name)
        end
    end
    return itemName
end

function RuneManager.GetRuneTotalAttr(runeInfo)
    if runeInfo then
        local runeCfg = this.GetRuneCfgInfo(runeInfo.itemModelId,runeInfo.level)
        local baseAttr = runeCfg.f_BaseAttr
        local advanceAttr1 = runeCfg.f_AdvanceAttr1
        local advanceAttr2 = runeCfg.f_AdvanceAttr2
        local advanceAttr3 = runeCfg.f_AdvanceAttr3
        local baptismAttr  = runeInfo.baptismAttr
        local totalAttr = {}
        for k,v in pairs(baseAttr) do
            if totalAttr[v[1]] then
                totalAttr[v[1]] = totalAttr[v[1]]+v[2]
            else
                totalAttr[v[1]] = v[2]
            end
        end
        if advanceAttr1 and advanceAttr1 ~= "" then
            for k,v in pairs(advanceAttr1) do
                if totalAttr[v[1]] then
                    totalAttr[v[1]] = totalAttr[v[1]]+v[2]
                else
                    totalAttr[v[1]] = v[2]
                end
            end
        end
        for k,v in pairs(baptismAttr) do
            if totalAttr[v[1]] then
                totalAttr[v[1]] = totalAttr[v[1]]+v[2]
            else
                totalAttr[v[1]] = v[2]
            end
        end
        local factor = 1
        if advanceAttr2 and advanceAttr2 ~= "" then
            factor = factor + (tonumber(advanceAttr2)/100)
        end
        if advanceAttr3 and advanceAttr3 ~= "" then
            factor = factor + (tonumber(advanceAttr3)/100)
        end
        for k,v in pairs(totalAttr) do
            v = v*factor
        end
        return totalAttr
    end
end

function RuneManager.GetTotalAttr(attrMap)
    local attrList = {}
    for k,v in pairs(attrMap) do
        local oneAttr = {}
        oneAttr[1] = k
        oneAttr[2] = v
        table.insert(attrList, oneAttr)
    end
end

function RuneManager.OnDestroy()
    this.runeCfg = {}
    this.runeStrengthCfg = {}
    this.runeSuit = {}
end

return RuneManager